﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration.Conventions;

using MiniSched.Orm.Enumerations;

namespace MiniSched.Orm {
    
    public class MiniSchedContext : DbContext {

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {

            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
            modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

            base.OnModelCreating(modelBuilder);
        }

        public IDbSet<Event> Events { get; set; }
        public IDbSet<EventJob> EventJobs { get; set; }
        public IDbSet<Job> Jobs { get; set; }
        public IDbSet<Organization> Organizations { get; set; }
        public IDbSet<OrganizationEvent> OrganizationEvents { get; set; }
        public IDbSet<RecurrenceType> RecurrenceTypes { get; set; }
        public IDbSet<Role> Roles { get; set; }
        public IDbSet<ScheduledEvent> ScheduledEvents { get; set; }
        public IDbSet<ScheduledJob> ScheduledJobs { get; set; }
        public IDbSet<UserProfile> UserProfiles { get; set; }
        public IDbSet<UserRole> UserRoles { get; set; }
        public IDbSet<Volunteer> Volunteers { get; set; }
        public IDbSet<VolunteerJob> VolunteerJobs { get; set; }

        public TEntity GetOrCreate<TEntity>(Expression<Func<TEntity, bool>> selector, Func<TEntity> create) where TEntity : class {
            if (null == create) throw new ArgumentNullException("create");

            var set = Set<TEntity>();
            if (set == null) throw new InvalidOperationException();

            var entity = set.FirstOrDefault(selector);
            if (entity == null) {
                set.Add(entity = create());
            }

            return entity;
        }

        public TEntity GetOrCreate<TEntityOption, TEntity>(TEntityOption option)
            where TEntityOption : EnumEntityOption<TEntity, TEntityOption>
            where TEntity : EnumEntity<TEntityOption, TEntity>, new()
        {
            var name = option.Name;
            return GetOrCreate<TEntity>(e => e.Name == name, () => new TEntity { Name = name });
        }
    }
}
